package com.weixin.sdk.pay;

import com.weixin.sdk.kit.WxSdkPropKit;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.SocketTimeoutException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.TreeMap;
import javax.net.ssl.SSLContext;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.ConnectionPoolTimeoutException;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

public abstract class PaycertApi extends PayApi {
	private boolean hasInit = false;

	private int socketTimeout = 10000;

	private int connectTimeout = 30000;
	private RequestConfig requestConfig;
	private CloseableHttpClient httpClient;

	public BaseResData post(BaseReq reqData, byte[] certs) throws Exception {
		TreeMap map = reqData.toMap();
		String mchId = map.get("mch_id") != null ? map.get("mch_id").toString() : WxSdkPropKit.get("wx_app_id");
		if (!this.hasInit) {
			init(certs, mchId);
		}
		String result = null;
		HttpPost httpPost = new HttpPost(getApiUrl());

		String postDataXML = getRequestXml(map);

		StringEntity postEntity = new StringEntity(postDataXML, "UTF-8");
		httpPost.addHeader("Content-Type", "text/xml");
		httpPost.setEntity(postEntity);

		httpPost.setConfig(this.requestConfig);
		try {
			HttpResponse response = this.httpClient.execute(httpPost);
			HttpEntity entity = response.getEntity();
			result = EntityUtils.toString(entity, "UTF-8");
		} catch (ConnectionPoolTimeoutException e) {
			e.printStackTrace();
		} catch (ConnectTimeoutException e) {
			e.printStackTrace();
		} catch (SocketTimeoutException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			httpPost.abort();
		}
		return getRespone(getResponseRoot(result));
	}

	private void init(byte[] certs, String mchId) throws IOException, KeyStoreException, UnrecoverableKeyException,
			NoSuchAlgorithmException, KeyManagementException {
		KeyStore keyStore = KeyStore.getInstance("PKCS12");
		FileInputStream instream = new FileInputStream(new File(WxSdkPropKit.get("cert_local_path")));
		System.setProperty("javax.net.ssl.trustStore",WxSdkPropKit.get("cert_local_path"));
		//InputStream instream = new ByteArrayInputStream(certs);
		try {
			keyStore.load(instream, mchId.toCharArray());
		} catch (CertificateException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} finally {
			instream.close();
		}

		SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mchId.toCharArray()).build();

		SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null,
				SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);

		this.httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();

		this.requestConfig = RequestConfig.custom().setSocketTimeout(this.socketTimeout)
				.setConnectTimeout(this.connectTimeout).build();
	}
}
